package org.linlinjava.litemall.mechanismadmin.web;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeOrderSettleModel;
import com.alipay.api.domain.OpenApiRoyaltyDetailInfoPojo;
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.builder.AlipayTradeRefundRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.model.result.AlipayF2FRefundResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.alipay.config.AliPayProperties;
import org.linlinjava.litemall.core.config.AES;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallMechanism;
import org.linlinjava.litemall.db.domain.LitemallWalletRecord;
import org.linlinjava.litemall.db.domain.ProxyIntroduce;
import org.linlinjava.litemall.db.service.LitemallMechanismService;
import org.linlinjava.litemall.db.service.LitemallProxyService;
import org.linlinjava.litemall.db.service.LitemallWalletRecordService;
import org.linlinjava.litemall.mechanismadmin.annotation.LoginAdmin;
import org.linlinjava.litemall.mechanismadmin.dao.CreateProxyMerchanism;
import org.linlinjava.litemall.mechanismadmin.dao.RenewProxy;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * 代理商户
 *
 * @author zhy
 * @date 2019-01-22 10:58
 **/
@RestController
@RequestMapping("/mechanismadmin/proxy")
public class MerchanismProxyContoller {
	private final Log logger = LogFactory.getLog(MerchanismProxyContoller.class);

	private AliPayProperties aliPayProperties;

	private AlipayTradeService alipayTradeService;

	private LitemallProxyService litemallProxyService;

	private LitemallMechanismService mechanismService;

	private LitemallWalletRecordService recordService;

	private final static String TRADE_SUCCESS = "TRADE_SUCCESS";

	private final static String TRADE_FINISHED = "TRADE_FINISHED";

	private final static String LEVEL_ONE = "1";

	private final static String LEVEL_FOUR = "4";

	private AlipayClient alipayClient;

	public MerchanismProxyContoller(
		AliPayProperties aliPayProperties,
		AlipayTradeService alipayTradeService,
		LitemallProxyService litemallProxyService,
		LitemallMechanismService mechanismService,
		LitemallWalletRecordService recordService) {
		this.aliPayProperties = aliPayProperties;
		this.alipayTradeService = alipayTradeService;
		this.litemallProxyService = litemallProxyService;
		this.mechanismService = mechanismService;
		this.recordService = recordService;
	}

	/**
	 * 3,4等级
	 */
	private static ArrayList<String> ARRAY_LEVEL3_LEVEL4 = new ArrayList<String>() {{
		add("3");
		add("4");
	}};

	private AlipayClient getAlipayClient() {
		if (alipayClient == null) {
			createClient();
		}
		return alipayClient;
	}

	private synchronized void createClient() {
		if (alipayClient == null) {
			alipayClient = new DefaultAlipayClient(aliPayProperties.getOpenApiDomain(),
				aliPayProperties.getAppid(),
				aliPayProperties.getPrivateKey(),
				"json",
				"GBK",
				aliPayProperties.getAlipayPublicKey(),
				"RSA2");
		}
	}

	/**
	 *通过交易单号查询交易状态
	 * @param outTradeNo
	 * @return
	 */
	@PostMapping("/queryStatus")
	public Object queryStatus(String outTradeNo){
		String values = "";
		String tradeNo = "";
		String successState ="10000";
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
		request.setBizContent("{" +
			"\"out_trade_no\":\""+outTradeNo+"\"" +
			"  }");
		try {
			AlipayTradeQueryResponse response = getAlipayClient().execute(request,"", aliPayProperties.getAppAuthToken());
			if (successState.equals(response.getCode())) {
				switch (response.getTradeStatus()) {
					case "WAIT_BUYER_PAY":
						values = "WAIT_BUYER_PAY";
						break;
					case "TRADE_SUCCESS":
						values = "TRADE_SUCCESS";
						tradeNo = response.getTradeNo();
						break;
					case "TRADE_CLOSED":
						values = "TRADE_CLOSED";
						break;
					case "TRADE_FINISHED":
						values = "TRADE_FINISHED";
						tradeNo = response.getTradeNo();
						break;
					default:
						values = "QUERY_FAILURE";
				}
			}else {
				values = "QUERY_FAILURE";
			}
		}catch (AlipayApiException e) {
			e.printStackTrace();
		}
		Map<String,Object > map = new HashMap<>(2);
		map.put("values",values);
		map.put("tradeNo",tradeNo);
		return ResponseUtil.ok(map);
	}
	/**
	 * 分账测试
	 *
	 * @return 成功
	 */
	@GetMapping("/payTest")
	public Object payTest() {
		AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
		AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
		//该笔分账的请求单号，每一次请求保证唯一
		model.setOutRequestNo("20190124220014193");
		//分账的交易的支付宝交易号
		model.setTradeNo("2019012422001419371011504764");
		// 声明OpenApiRoyaltyDetailInfoPojo方法用于传入royaltyParameters
		OpenApiRoyaltyDetailInfoPojo openApiRoyaltyDetailInfoPojo = new OpenApiRoyaltyDetailInfoPojo();
		//分出账户,也就是商家的账户pid
		openApiRoyaltyDetailInfoPojo.setTransOut("2088921275298603");
		//分账金额收款账户pid
		openApiRoyaltyDetailInfoPojo.setTransIn("2088112240819372");
		openApiRoyaltyDetailInfoPojo.setAmount((long)0.01);

		List<OpenApiRoyaltyDetailInfoPojo> royaltyParameters1 = new ArrayList<>();
		royaltyParameters1.add(openApiRoyaltyDetailInfoPojo);

		model.setRoyaltyParameters(royaltyParameters1);
		request.setBizModel(model);
		try {
			AlipayTradeOrderSettleResponse response = getAlipayClient().execute(request, "", aliPayProperties.getAppAuthToken());
			if (response.isSuccess()) {
				System.out.println("调用成功");
			} else {
				System.out.println("调用失败");
			}
		}
		catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return ResponseUtil.ok();
	}

	@GetMapping("/queryPicurl")
	public Object queryPicurl(String pictureId){
		try {
			if (!StringUtils.isEmpty(pictureId) ) {
				pictureId = new String(AES.decrypt(pictureId, AES.getKey()), StandardCharsets.UTF_8);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			return ResponseUtil.fail(403, "解密失败");
		}
		ProxyIntroduce proxyIntroduce = litemallProxyService.findById(Integer.parseInt(pictureId));
		ProxyIntroduce proxyIntroduce1 = new ProxyIntroduce();
		proxyIntroduce1.setIntrodecPicture(proxyIntroduce.getIntrodecPicture());
		return ResponseUtil.ok(proxyIntroduce1);
	}
	/**
	 * 退款，退款成功后，将机构的信息删除，将状态改为已退款 checkStatus6
	 *
	 * @param id 申请退款时机构信息的id
	 * @return 退款失败返回失败原因，退款成功在前端展示成功信息
	 */
	@GetMapping("/refund")
	public Object refundFee(String id,String recordSn) {
		try {
			if (!StringUtils.isEmpty(id) && !StringUtils.isEmpty(recordSn)) {
				id = new String(AES.decrypt(id, AES.getKey()), StandardCharsets.UTF_8);
				recordSn = new String(AES.decrypt(recordSn, AES.getKey()), StandardCharsets.UTF_8);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
			return ResponseUtil.fail(403, "解密失败");
		}
		logger.info("订单号为" + id + "的用户申请退款");
		// 取出钱包记录里的金额，单号
		LitemallWalletRecord litemallWalletRecord = recordService.queryRecordSn(recordSn);
		String tradeNo = litemallWalletRecord.getPayId();
		String refundAmount = litemallWalletRecord.getActualPayment().toString();
		// 填写模板，发送退款请求
		AlipayTradeRefundRequestBuilder builder =
			new AlipayTradeRefundRequestBuilder().setTradeNo(tradeNo).setRefundAmount(refundAmount).setRefundReason("取消成为爱能机构代理").setAppAuthToken(aliPayProperties.getAppAuthToken());
		AlipayF2FRefundResult result = alipayTradeService.tradeRefund(builder);
		logger.info("退款金额：" + refundAmount + ",支付订单号：" + tradeNo + ",状态：" + result.getTradeStatus());
		LitemallMechanism mechanism = new LitemallMechanism();
		switch (result.getTradeStatus()) {
			case SUCCESS:
				//将机构状态改为已经退款
				mechanism.setCheckStatus((byte)5);
				mechanism.setId(Integer.parseInt(id));
				int flag = mechanismService.updateById(mechanism);
				logger.info(id + "数据更新状态" + flag);
				break;
			case FAILED:
				mechanism.setCheckStatus((byte)6);
				mechanism.setId(Integer.parseInt(id));
				int flags = mechanismService.updateById(mechanism);
				logger.info(id + "数据更新状态" + flags);
				return ResponseUtil.fail(-1, "退款失败");
			case UNKNOWN:
				return ResponseUtil.fail(-1, "请求失败，稍后再试");
			default:
				return ResponseUtil.fail(-1, "请求失败，稍后再试");
		}

		return ResponseUtil.ok();
	}

//	/**
//	 * 通过机构号id发起退款
//	 * @param id
//	 * @return
//	 */
//	@GetMapping("/refundFees")
//	public Object refundFees(String id) {
//		logger.info("机构号为" + id + "的用户申请退款");
//		// 取出钱包记录里的金额，单号
//		LitemallWalletRecord litemallWalletRecord = recordService.queryRecordSn(id);
//		String tradeNo = litemallWalletRecord.getPayId();
//		String refundAmount = litemallWalletRecord.getActualPayment().toString();
//		// 填写模板，发送退款请求
//		AlipayTradeRefundRequestBuilder builder =
//			new AlipayTradeRefundRequestBuilder().setTradeNo(tradeNo).setRefundAmount(refundAmount).setRefundReason("取消成为爱能机构代理").setAppAuthToken(aliPayProperties.getAppAuthToken());
//		AlipayF2FRefundResult result = alipayTradeService.tradeRefund(builder);
//		logger.info("退款金额：" + refundAmount + ",支付订单号：" + tradeNo + ",状态：" + result.getTradeStatus());
//
//		switch (result.getTradeStatus()) {
//			case SUCCESS:
//				System.out.println("成功");
//				break;
//			case FAILED:
//				return ResponseUtil.fail(-1, "退款失败");
//			case UNKNOWN:
//				return ResponseUtil.fail(-1, "请求失败，稍后再试");
//			default:
//				return ResponseUtil.fail(-1, "请求失败，稍后再试");
//		}
//
//		return ResponseUtil.ok();
//	}
	/**
	 * 正式用户续费
	 *
	 * @return 成功
	 */
	@PostMapping("/renewProxy")
	public Object renewProxy(@LoginAdmin Integer adminId, @RequestBody RenewProxy renewProxy) {
		if (adminId == null) {
			return ResponseUtil.unlogin();
		}
		String level = renewProxy.getLevel();
		String recordSn = renewProxy.getRecordSn();
		String orgId = renewProxy.getOrgId();
		try {
			level = new String(AES.decrypt(level, AES.getKey()), StandardCharsets.UTF_8);
		}
		catch (Exception e) {
			e.printStackTrace();
			return ResponseUtil.fail(403, "解密失败");
		}
		int levels = Integer.parseInt(level);
		if(levels==1){
           return ResponseUtil.fail(-1,"体验用户暂不开放");
		}else if(levels==4){
			return ResponseUtil.fail(-1,"开通商圈事业部请联系爱联商圈负责人");
		}
		//获取支付的金额
		ProxyIntroduce proxyIntroduce = litemallProxyService.findById(Integer.parseInt(level));

		LitemallWalletRecord litemallWalletRecord = new LitemallWalletRecord();
		litemallWalletRecord.setMechaismId(adminId);
		litemallWalletRecord.setRecordSn(recordSn);
		litemallWalletRecord.setOrgId(Integer.parseInt(orgId));
		litemallWalletRecord.setType((byte)1);
		litemallWalletRecord.setModifyReason("续费爱联商圈代理：" + proxyIntroduce.getName());
		litemallWalletRecord.setActualPayment(proxyIntroduce.getFee());
		litemallWalletRecord.setPayLevel((byte)levels);
		recordService.add(litemallWalletRecord);
		//充值时间等充值成功后再添加上去

		//发起请求
		AlipayTradePrecreateResponse res;
		//付款金额
		String fee = proxyIntroduce.getFee().toString();
		//订单名称，必填
		String subject = proxyIntroduce.getName();
		//商品描述，可空
		String body = "";
		String timeoutExpress = "15m";
		ExtendParams extendParams = new ExtendParams();
		extendParams.setSysServiceProviderId(aliPayProperties.getPid());

		AlipayTradePrecreateRequestBuilder builder =
			new AlipayTradePrecreateRequestBuilder().setSubject(subject).setTotalAmount(fee).setOutTradeNo(recordSn).setBody(body).setTimeoutExpress(timeoutExpress)
				.setAppAuthToken(aliPayProperties.getAppAuthToken()).setStoreId(orgId)
				//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
				.setNotifyUrl(aliPayProperties.getProxyNotifyUrl()).setExtendParams(extendParams);
		AlipayF2FPrecreateResult preCreateResult = alipayTradeService.tradePrecreate(builder);
		switch (preCreateResult.getTradeStatus()) {
			case SUCCESS:
				res = preCreateResult.getResponse();
				break;
			case FAILED:
				return ResponseUtil.fail(-1, "支付宝预下单失败,稍后再试");
			case UNKNOWN:
				return ResponseUtil.fail(-1, "支付宝预下单失败");
			default:
				return ResponseUtil.fail(-1, "支付宝预下单失败");
		}
		return ResponseUtil.ok(res.getQrCode());
	}

	/**
	 * 1.散户创建自己的机构账户,此时账户的状态是deleted=1，check_status=0, 即填单未交钱，账户是删除的
	 * 2.创建成功后获取用户id,向钱包记录里插入一条记录，用来记录付款是否已经成功
	 * 3.向支付宝发起支付请求，将二维码返回到前端
	 *
	 * @param createProxyMerchanism 请求类
	 * @return 成功
	 */
	@PostMapping("/createProxy")
	public Object createProxy(@RequestBody CreateProxyMerchanism createProxyMerchanism) {
		LitemallMechanism ad = createProxyMerchanism.getLitemallMechanism();
		String recordSn = createProxyMerchanism.getRecordSn();
		String levels = createProxyMerchanism.getLevel();
		//解密level
		try {
			levels = new String(AES.decrypt(levels, AES.getKey()), StandardCharsets.UTF_8);
		}
		catch (Exception e) {
			e.printStackTrace();
			return ResponseUtil.fail(401, "解密失败");
		}
		if(LEVEL_ONE.equals(levels)){
			return ResponseUtil.fail(-1,"体验用户暂不开放");
		}else if(LEVEL_FOUR.equals(levels)){
			return ResponseUtil.fail(-1,"开通商圈事业部请联系爱联商圈负责人");
		}
		if(ARRAY_LEVEL3_LEVEL4.contains(levels)){
			ad.setProxyUseFlag(true);
		}
		ad.setCheckStatus((byte)0);
		ad.setLevel((byte)Integer.parseInt(levels));
		ad.setUpdateTime(LocalDateTime.now());
		ad.setDeleted(false);
		ad.setIntegralAmountAll((long)1000000);
		mechanismService.add(ad);
		if (StringUtils.isEmpty(ad.getId())) {
			return ResponseUtil.fail(-1, "数据保存失败!");
		}
		//获取支付的金额
		ProxyIntroduce proxyIntroduce = litemallProxyService.findById(Integer.parseInt(levels));

		//创建钱包记录
		LitemallWalletRecord litemallWalletRecord = new LitemallWalletRecord();
		litemallWalletRecord.setRecordSn(recordSn);
		litemallWalletRecord.setOrgId(ad.getId());
		litemallWalletRecord.setType((byte)1);
		litemallWalletRecord.setPayType((byte)1);
		litemallWalletRecord.setPayLevel((byte)Integer.parseInt(levels));
		litemallWalletRecord.setModifyReason("爱联商圈" + proxyIntroduce.getName());
		litemallWalletRecord.setActualPayment(proxyIntroduce.getFee());
		recordService.add(litemallWalletRecord);
		//充值时间等充值成功后再添加上去

		//发起请求
		AlipayTradePrecreateResponse res;
		//付款金额
		String fee = proxyIntroduce.getFee().toString();
		//订单名称，必填
		String subject = proxyIntroduce.getName();
		//商品描述，可空
		String body = "";
		String timeoutExpress = "15m";
		ExtendParams extendParams = new ExtendParams();
		extendParams.setSysServiceProviderId(aliPayProperties.getPid());

		AlipayTradePrecreateRequestBuilder builder =
			new AlipayTradePrecreateRequestBuilder().setSubject(subject).setTotalAmount(fee).setOutTradeNo(recordSn).setBody(body).setTimeoutExpress(timeoutExpress)
				.setAppAuthToken(aliPayProperties.getAppAuthToken()).setStoreId(ad.getId().toString())
				//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
				.setNotifyUrl(aliPayProperties.getProxyNotifyUrl()).setExtendParams(extendParams);
		AlipayF2FPrecreateResult preCreateResult = alipayTradeService.tradePrecreate(builder);
		switch (preCreateResult.getTradeStatus()) {
			case SUCCESS:
				res = preCreateResult.getResponse();
				break;
			case FAILED:
				return ResponseUtil.fail(-1, "支付宝预下单失败");
			case UNKNOWN:
				return ResponseUtil.fail(-1, "支付宝预下单失败");
			default:
				return ResponseUtil.fail(-1, "支付宝预下单失败");
		}
		return ResponseUtil.ok(res.getQrCode());
	}

	/**
	 * 支付回调
	 * 获取代理充值成功后，将该账户的充值时间,支付id填上
	 * 并将机构的状态改为1
	 *
	 * @param request 支付宝请求
	 * @return 成功
	 */
	@PostMapping("/returnProxyAliPayStatus")
	public String returnProxyAliPayStatus(HttpServletRequest request) {
		logger.info(request);
		String message="";
		String outTradeNum;
		try {
			String tradeStatus = new String(request.getParameter("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
			if (TRADE_SUCCESS.equals(tradeStatus) || TRADE_FINISHED.equals(tradeStatus)) {
				outTradeNum = new String(request.getParameter("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
				String tradeNo = new String(request.getParameter("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
				String gmtPayment = new String(request.getParameter("gmt_payment").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
				Date ds = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(gmtPayment);
				LocalDateTime ldt = LocalDateTime.ofInstant(ds.toInstant(), ZoneId.systemDefault());
				LitemallWalletRecord litemallWalletRecord = recordService.queryByRecordSn(outTradeNum);
				int orgId = litemallWalletRecord.getOrgId();
				// 将机构审核状态改为1（已交钱）
				LitemallMechanism litemallMechanism1 = new LitemallMechanism();
				litemallMechanism1.setCheckStatus((byte)1);
				litemallMechanism1.setId(orgId);
				mechanismService.updateById(litemallMechanism1);
				if (litemallWalletRecord.getPayId() == null) {
					litemallWalletRecord.setPayId(tradeNo);
					litemallWalletRecord.setPayTime(ldt);
					recordService.update(litemallWalletRecord);
					//如果是机构自己升级，设置机构状态为1
					if (litemallWalletRecord.getPayLevel() != null) {
						LitemallMechanism litemallMechanism = mechanismService.findById(litemallWalletRecord.getOrgId());
						litemallMechanism.setLevel(litemallWalletRecord.getPayLevel());
						if(ARRAY_LEVEL3_LEVEL4.contains(String.valueOf(litemallWalletRecord.getPayLevel()))){
							litemallMechanism.setProxyUseFlag(true);
						}
						litemallMechanism.setCheckStatus((byte)1);
						mechanismService.updateById(litemallMechanism);
					}
					message="SUCCESS";
				}
			}
		}
		catch (ParseException e) {
			e.printStackTrace();
			return "failure";
		}
		return message;
	}

	/**
	 * 前端查询支付宝是否已经收费成功，成功后关闭二维码
	 */
	@GetMapping("/queryAliPayStatus")
	public Object queryAliPayStatus(String recordSn) {
		Map<String, Object> data = new HashMap<>(16);
		LitemallWalletRecord walletRecord = recordService.queryRecordSn(recordSn);
		if (walletRecord != null && !StringUtils.isEmpty(walletRecord.getPayId())) {
			data.put("orderStatus", "SUCCESS");
		} else {
			data.put("orderStatus", "WAIT_PAY");
		}
		return ResponseUtil.ok(data);
	}
}
